package com.yunying.rispro.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yunying.rispro.exception.BusinessException;
import com.yunying.rispro.model.Doctor;
import com.yunying.rispro.mapper.DoctorMapper;
import com.yunying.rispro.service.IDoctorService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yunying.rispro.service.IRedisService;
import com.yunying.rispro.util.*;
import com.yunying.rispro.vo.UserVo;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 医生信息表 服务实现类
 * </p>
 *
 * @author yunying
 * @since 2022-04-21
 */
@Service
@Transactional //事务：若添加用户出错(如服务器崩了)，数据库不能有数据
public class DoctorServiceImpl extends ServiceImpl<DoctorMapper, Doctor> implements IDoctorService {

    private static final String slat = "rngnb!@###"; //加密盐

    @Autowired
    private DoctorMapper doctorMapper;

    @Autowired
    private IRedisService redisService;

    @Override
    public JsonResponseBody<?> login(UserVo userVo, HttpServletRequest req, HttpServletResponse resp) {
        /*
        1.检查参数是否合法
        2.根据用户名密码查询user是否存在
        3.不存在 登陆失败
        4.存在使用jwt 生成token返回给前端
        5.将token放入redis中，redis token:user信息，设置过期时间
        （登录认证先认证字符串是否合法，再去redis认证是否存在）
         */
        // 根据工号获取对应用户对象信息
        Doctor user = doctorMapper.selectOne(new QueryWrapper<Doctor>().eq("doctor_id", userVo.getDoctorId()));
        // 判断用户对象是否存在
        if(user==null){
            throw new BusinessException(JsonResponseStatus.USER_EMPTY);
        }
        // 判断用户对象的密码与输入的密码是否一致
        // 注：将前端传入的一道加密密码与user对象中的随机盐进行二次加密得到二道密码，再与数据库进行比较
        String pwd2= MD5Utils.formPassToDbPass(userVo.getPassword(),user.getSalt());
        if(!user.getDoctorPwd().equals(pwd2)){
            throw new BusinessException(JsonResponseStatus.PASSWORD_ERROR);
        }
        //1.采用UUID方式作为Token令牌
        String token = JWTUtils.createToken(userVo.getDoctorId());
        //2.将生成的Token令牌保存到cookie中
        CookieUtils.setCookie(req,resp,"token",token,1800);
        //3.将生成的Token与user对象进行绑定并保存到redis中
        redisService.setUserToRedis(token,user);

        return new JsonResponseBody<>();
    }

    @Override
    public JsonResponseBody<?> logout(String token) {
        //后端只需要清除redis的token
        redisService.deleteToken(token);
        return new JsonResponseBody<>();
    }

    //检验token，主要给拦截处理器使用
    @Override
    public Doctor checkToken(String token) {
        /*
        1.token合法性校验（是否为空，解析是否成功，redis是否存在）
        2.校验失败，返回错误；校验成功，返回结果LoginVo
         */
        if(StringUtils.isBlank(token)){
            return null;
        }
        //判断token是否能解析成功
        Map<String, Object> stringObjectMap = JWTUtils.checkToken(token);
        if(stringObjectMap == null){
            return null;
        }

        //从rides拿到对应user json字符串
        Doctor user = redisService.getUserByToken(token);
        if(user==null){
            return null;
        }
        return user;
    }

}
